package com.ruoyi.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 虚拟线程监控组件
 * 提供虚拟线程的实时监控和性能统计
 * 
 * @author ruoyi
 */
@Component
public class VirtualThreadMonitor {
    
    private static final Logger performanceLogger = LoggerFactory.getLogger("virtual-thread-performance");
    private static final Logger virtualThreadLogger = LoggerFactory.getLogger("virtual-thread");
    
    private final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
    private final AtomicLong totalVirtualThreads = new AtomicLong(0);
    private final AtomicLong totalPlatformThreads = new AtomicLong(0);
    private final AtomicLong totalRequests = new AtomicLong(0);
    
    private volatile boolean monitoringEnabled = true;
    
    /**
     * 应用启动完成后开始监控
     */
    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReady() {
        virtualThreadLogger.info("虚拟线程监控系统启动完成，开始实时监控...");
        logSystemInfo();
    }
    
    /**
     * 每30秒记录一次线程池状态
     */
    @Scheduled(fixedRate = 30000)
    @Async
    public void logThreadPoolStatus() {
        if (!monitoringEnabled) {
            return;
        }
        
        try {
            // 获取线程信息
            int threadCount = threadMXBean.getThreadCount();
            int peakThreadCount = threadMXBean.getPeakThreadCount();
            long totalStartedThreadCount = threadMXBean.getTotalStartedThreadCount();
            
            // 获取内存信息
            Runtime runtime = Runtime.getRuntime();
            long freeMemory = runtime.freeMemory() / (1024 * 1024);
            long totalMemory = runtime.totalMemory() / (1024 * 1024);
            long maxMemory = runtime.maxMemory() / (1024 * 1024);
            long usedMemory = totalMemory - freeMemory;
            
            // 记录监控信息
            performanceLogger.info("=== 虚拟线程监控报告 [{}] ===", 
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            performanceLogger.info("线程统计 | 当前线程数: {} | 峰值线程数: {} | 总启动线程数: {}", 
                threadCount, peakThreadCount, totalStartedThreadCount);
            
            performanceLogger.info("内存统计 | 已用: {}MB | 空闲: {}MB | 总计: {}MB | 最大: {}MB | 使用率: {:.2f}%", 
                usedMemory, freeMemory, totalMemory, maxMemory, (double)usedMemory / totalMemory * 100);
            
            performanceLogger.info("请求统计 | 总请求数: {} | 虚拟线程数: {} | 平台线程数: {}", 
                totalRequests.get(), totalVirtualThreads.get(), totalPlatformThreads.get());
            
            // 检查内存使用情况
            double memoryUsagePercent = (double)usedMemory / totalMemory * 100;
            if (memoryUsagePercent > 80) {
                performanceLogger.warn("警告：内存使用率过高 {}%，建议检查内存泄漏", String.format("%.2f", memoryUsagePercent));
            }
            
            // 检查线程数量
            if (threadCount > 1000) {
                performanceLogger.warn("警告：当前线程数过多 {}，可能存在线程泄漏", threadCount);
            }
            
        } catch (Exception e) {
            virtualThreadLogger.error("监控线程池状态时发生错误", e);
        }
    }
    
    /**
     * 每分钟记录一次详细的性能统计
     */
    @Scheduled(fixedRate = 60000)
    @Async
    public void logDetailedPerformanceStats() {
        if (!monitoringEnabled) {
            return;
        }
        
        try {
            // 获取CPU信息
            double cpuUsage = getCpuUsage();
            
            // 获取GC信息
            String gcInfo = getGarbageCollectionInfo();
            
            performanceLogger.info("=== 详细性能统计 [{}] ===", 
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            
            performanceLogger.info("CPU使用率: {:.2f}%", cpuUsage);
            performanceLogger.info("GC信息: {}", gcInfo);
            
            // 记录虚拟线程相关的JVM参数
            String parallelism = System.getProperty("jdk.virtualThreadScheduler.parallelism", "未设置");
            String maxPoolSize = System.getProperty("jdk.virtualThreadScheduler.maxPoolSize", "未设置");
            
            performanceLogger.info("虚拟线程配置 | 并行度: {} | 最大池大小: {}", parallelism, maxPoolSize);
            
        } catch (Exception e) {
            virtualThreadLogger.error("记录详细性能统计时发生错误", e);
        }
    }
    
    /**
     * 记录请求处理统计
     */
    public void recordRequest(boolean isVirtualThread) {
        totalRequests.incrementAndGet();
        if (isVirtualThread) {
            totalVirtualThreads.incrementAndGet();
        } else {
            totalPlatformThreads.incrementAndGet();
        }
    }
    
    /**
     * 获取CPU使用率
     */
    private double getCpuUsage() {
        try {
            long startTime = System.nanoTime();
            long startCpuTime = threadMXBean.getCurrentThreadCpuTime();
            
            Thread.sleep(100); // 等待100ms
            
            long endTime = System.nanoTime();
            long endCpuTime = threadMXBean.getCurrentThreadCpuTime();
            
            double cpuUsage = ((double)(endCpuTime - startCpuTime)) / (endTime - startTime) * 100;
            return Math.max(0, Math.min(100, cpuUsage));
        } catch (Exception e) {
            return -1;
        }
    }
    
    /**
     * 获取垃圾回收信息
     */
    private String getGarbageCollectionInfo() {
        try {
            return ManagementFactory.getGarbageCollectorMXBeans().stream()
                .map(gc -> String.format("%s(回收次数:%d,耗时:%dms)", 
                    gc.getName(), gc.getCollectionCount(), gc.getCollectionTime()))
                .reduce((a, b) -> a + ", " + b)
                .orElse("无GC信息");
        } catch (Exception e) {
            return "获取GC信息失败";
        }
    }
    
    /**
     * 记录系统启动信息
     */
    private void logSystemInfo() {
        virtualThreadLogger.info("=== 系统信息 ===");
        virtualThreadLogger.info("Java版本: {}", System.getProperty("java.version"));
        virtualThreadLogger.info("虚拟线程支持: {}", supportsVirtualThreads());
        virtualThreadLogger.info("可用处理器: {}", Runtime.getRuntime().availableProcessors());
        virtualThreadLogger.info("最大内存: {}MB", Runtime.getRuntime().maxMemory() / (1024 * 1024));
        virtualThreadLogger.info("操作系统: {} {}", 
            System.getProperty("os.name"), System.getProperty("os.version"));
    }
    
    /**
     * 检查是否支持虚拟线程
     */
    private boolean supportsVirtualThreads() {
        try {
            Thread.ofVirtual().name("test-support").start(() -> {}).isVirtual();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    /**
     * 启用/禁用监控
     */
    public void setMonitoringEnabled(boolean enabled) {
        this.monitoringEnabled = enabled;
        virtualThreadLogger.info("虚拟线程监控 {}", enabled ? "已启用" : "已禁用");
    }
    
    /**
     * 获取监控统计信息
     */
    public String getMonitoringStats() {
        StringBuilder stats = new StringBuilder();
        stats.append("=== 监控统计信息 ===\n");
        stats.append("总请求数: ").append(totalRequests.get()).append("\n");
        stats.append("虚拟线程请求数: ").append(totalVirtualThreads.get()).append("\n");
        stats.append("平台线程请求数: ").append(totalPlatformThreads.get()).append("\n");
        stats.append("虚拟线程使用率: ").append(
            String.format("%.2f%%", (double)totalVirtualThreads.get() / totalRequests.get() * 100)).append("\n");
        stats.append("当前线程数: ").append(threadMXBean.getThreadCount()).append("\n");
        stats.append("峰值线程数: ").append(threadMXBean.getPeakThreadCount()).append("\n");
        return stats.toString();
    }
} 